home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-02 / tpmemo.zip / TPMEMO.DOC < prev    next >
Text File  |  1993-01-04  |  35KB  |  812 lines

  1. TPMEMO - Memo field editor for Turbo Professional 5.0
  2. -----------------------------------------------------
  3. Version 1.0
  4. Copyright (c) 1988 by TurboPower Software
  5.  
  6. Overview
  7. ------------------------------------------------------------------------------
  8.  
  9. TPMEMO is a unit containing a simple text editor that can be used in programs
  10. written with Turbo Professional 5.0. We envision two primary uses for TPMEMO:
  11.  
  12. First, it can be used in conjunction with TPENTRY for editing 'memo fields' in
  13. database records. For a demonstration of how to use TPMEMO for this purpose,
  14. see ENTRY.PAS, discussed below in the section on Example Programs.
  15.  
  16. Second, TPMEMO can be used for editing text files. In this respect and others,
  17. TPMEMO is quite similar to Borland's Binary Editor (BINED), part of the Turbo
  18. Pascal Editor Toolbox. But there is one important feature in TPMEMO that is
  19. lacking in the Binary Editor: word wrap. In fact, one of our main goals in
  20. writing TPMEMO was to provide an alternative to BINED in cases where word wrap
  21. was essential. For an example of how to use TPMEMO for this purpose, see
  22. MEMO.PAS, discussed below in the section on Example Programs. The two other
  23. noteworthy advantages of TPMEMO over BINED are 1) built-in mouse support and
  24. 2) complete source code. The one major disadvantage of TPMEMO is that it does
  25. not implement any of the block manipulation commands found in BINED.
  26.  
  27. The sections that follow describe the various facilities in TPMEMO. None of
  28. these sections provides working examples of how to use these routines. For
  29. that you should look to ENTRY.PAS and MEMO.PAS.
  30.  
  31. Legal Matters
  32. -------------
  33.  
  34. In general, TPMEMO should be considered an official part of Turbo Professional
  35. 5.0, subject to the same restrictions that apply to other units in the
  36. package. The copyright notices in this and other files in the TPMEMO archive
  37. are binding. This is *not* public domain software.
  38.  
  39. However, because TPMEMO was developed after Turbo Professional 5.0 was
  40. released, and the demand for it is high, we have elected to post this file on
  41. CompuServe in order to distribute it to our existing customers free of charge.
  42. You may in turn upload this archive to other bulletin boards if you wish, but
  43. you may not distribute any of the other Turbo Professional units that it
  44. depends on, nor may you alter the contents of the archive in any way before
  45. uploading it.
  46.  
  47. Terminology
  48. ------------------------------------------------------------------------------
  49.  
  50. Before going any further, there are a few terms we need to define:
  51.  
  52. An 'edit window' is a region of the screen used to display text being edited
  53. with TPMEMO.
  54.  
  55. An 'edit buffer' is a data structure, usually an array of char, used to store
  56. the text being edited. The end of an edit buffer is always signalled by a ^Z
  57. (end of file) character. The end of each line of text within the edit buffer
  58. is signalled by a carriage return-line feed combination (^M^J). An 'empty'
  59. edit buffer should always be marked by a lone ^Z at the beginning of the
  60. buffer.
  61.  
  62. An 'editor control block' is a record variable used to store information about
  63. an edit window and the edit buffer associated with it, as well as a variety
  64. of status and housekeeping variables. See the entry for EMcontrolBlock in the
  65. next section for details on what an editor control block contains.
  66.  
  67. Routines in TPMEMO
  68. ------------------------------------------------------------------------------
  69.  
  70. This section covers the types, constants, and routines interfaced by TPMEMO.
  71.  
  72. Constants
  73.  
  74.   AllowTruncation : Boolean = True;
  75.  
  76.   This boolean constant determines whether or not ReadMemoFile will read in a
  77.   partial file in cases where the file is larger than the edit buffer.
  78.  
  79.   DisallowedInReadOnlyMode : set of EMtype =
  80.     [EMchar..EMenter, EMrestore, EMback..EMreformatG];
  81.  
  82.   The commands in this set are disallowed in read-only mode. It is interfaced
  83.   in case you need to add any user-defined commands to the set.
  84.  
  85.   EMnone       = 00; {Not a command}
  86.   ...
  87.   EMuser19     = 52;
  88.  
  89.   Each of these constants corresponds to an editing, cursor movement, or exit
  90.   command implemented by TPMEMO. See the section on Editing Commands, below,
  91.   for a discussion of these commands.
  92.  
  93.   ErrorRow : Byte = 1;      {default to top line of screen for error messages}
  94.   ErrorAttr : Byte = $F;    {attribute for error message line}
  95.  
  96.   These constants determine which row MemoError uses to display error
  97.   messages, and which video attribute they are displayed in. They are not used
  98.   unless you have enabled MemoError with the statement 'MemoErrorPtr :=
  99.   @MemoError;'.
  100.  
  101.   HelpForMemo = HelpForXXXX1;
  102.  
  103.   This constant represents the special code passed to a help routine to
  104.   indicate which unit the request for help came from. See the section on
  105.   Programming Hooks, below.
  106.  
  107.   IndentStartsParagraph : Boolean = False;
  108.  
  109.   If this constant is True, TPMEMO's paragraph reformatting routine treats a
  110.   blank space at the beginning of a line as signalling the start of a new
  111.   paragraph and hence the end of the previous one. If it is False, the end of
  112.   a paragraph is signalled by a blank line.
  113.  
  114.   MaxLineLength : Byte = 127;
  115.  
  116.   The maximum length of a line of text. This typed constant can be made
  117.   smaller, but under no circumstances should it be made larger. (The word wrap
  118.   routine needs to be able to store two complete lines of text in a single
  119.   string variable.)
  120.  
  121.   MemoErrorPtr : Pointer = nil;
  122.  
  123.   If not nil, this variable points to a routine that will be called each time
  124.   an error occurs. See the section on Programming Hooks, below.
  125.  
  126.   MemoHelpPtr : Pointer = nil;
  127.  
  128.   This variable points to a routine that will display help when <F1> is
  129.   pressed. If it is nil, pressing <F1> does nothing. See the section on
  130.   Programming Hooks, below.
  131.  
  132.   MemoKeyMax = 250;
  133.   MemoKeyID : string[16] = 'tpmemo key array';
  134.   MemoKeySet : array[0..MemoKeyMax] of Byte = (...);
  135.  
  136.   MemoKeySet contains the default key assignments for all the commands. See
  137.   the section on Programming Hooks, below.
  138.  
  139.   MemoKeyPtr : Pointer = nil;
  140.  
  141.   This variable points to a routine that will return the next keystroke. By
  142.   default it points to either TpMouse.ReadKeyOrButton (if mouse support is
  143.   enabled) or TpCrt.ReadKeyWord (if it isn't). See the section on Programming
  144.   Hooks, below.
  145.  
  146.   {$IFDEF UseMouse}
  147.   MemoMouseEnabled : Boolean = False;
  148.   {$ENDIF}
  149.  
  150.   This typed constant will be True if mouse support has been enabled by a call
  151.   to EnableMemoMouse.
  152.  
  153.   MemoStatusPtr : Pointer = nil;
  154.  
  155.   If not nil, this variable points to a routine that will be called at each
  156.   keystroke. Normally this routine will display a status line. See the section
  157.   on Programming Hooks, below.
  158.  
  159.   StatusRow : Byte = 2;      {default to second line of screen for status line}
  160.   StatusAttr : Byte = $F;    {attribute for status line}
  161.  
  162.   These constants determine which row MemoStatus uses to display a status
  163.   line, and which video attribute the status line is displayed in. They are
  164.   not used unless you have enabled MemoStatus with the statement
  165.   'MemoStatusPtr := @MemoStatus;'.
  166.  
  167.   tmBufferFull    = 1;       {edit buffer is full}
  168.   tmLineTooLong   = 2;       {line too long, CRLF inserted}
  169.   tmTooManyLines  = 3;       {max line limit has been reached}
  170.   tmOverLineLimit = 4;       {max line limit has been exceeded}
  171.  
  172.   These constants represent the possible error message codes passed to a
  173.   user-written error handler. See the section on Programming Hooks, below.
  174.  
  175. Types
  176.  
  177.   EMbuffer = array[1..65521] of Char;
  178.   EMcontrolBlock =           {an editor control block}
  179.     record
  180.       UserData : Pointer;    {reserved for user (ID number perhaps)}
  181.       XL, YL, XH, YH : Byte; {coordinates for edit window}
  182.       BufPtr : ^EMbuffer;    {pointer to text buffer}
  183.       BufSize : Word;        {size of buffer}
  184.       MaxLines : Integer;    {maximum number of lines}
  185.       TotalBytes : Word;     {bytes in buffer}
  186.       TotalLines : Integer;  {lines in buffer}
  187.       LineAtTop : Integer;   {line at top of edit window}
  188.       BufPosTop : Word;      {index into buffer for start of line at top}
  189.       CurLine : Integer;     {line number of current line}
  190.       BufPos : Word;         {index into buffer for start of current line}
  191.       CurCol : Byte;         {position of cursor within current line}
  192.       ColDelta : Byte;       {for horizontal scrolling}
  193.       KnownLine : Integer;   {used to speed up scrolling/searching}
  194.       KnownOfs : Word;       {"    "  "     "  "}
  195.       TAttr : Byte;          {attribute for normal text}
  196.       CAttr : Byte;          {attribute for control characters}
  197.       InsertMode : Boolean;  {True if in insert mode}
  198.       IndentMode : Boolean;  {True if in auto-indent mode}
  199.       WordWrap : Boolean;    {True if word wrap is on}
  200.       Modified : Boolean;    {True if edits have been made}
  201.       TabDelta : Byte;       {distance between tab stops}
  202.       Margin : Byte;         {right margin}
  203.       HelpTopic : Word;      {help topic}
  204.      end;
  205.  
  206.   Variables of this type are used to store information about a text editing
  207.   window and its associated buffer.
  208.  
  209.   EMtype = EMnone..EMuser19;
  210.  
  211.   A variable of this type is generally used to store the result of a call to
  212.   EditMemo, which always returns a value in the range EMnone..EMuser19.
  213.  
  214.   MemoStatusType = (
  215.     mstOK, mstNotFound, mstInvalidName, mstReadError, mstTooLarge,
  216.     mstTruncated, mstCreationError, mstWriteError, mstCloseError);
  217.  
  218.   ReadMemoFile and SaveMemoFile both return a function result of this type.
  219.   mstOK indicates that no error occurred. mstNotFound is returned by
  220.   ReadMemoFile if the specified file does not exist. It is not an error code;
  221.   it simply indicates that the user wants to edit a file that does not yet
  222.   exist. mstInvalidName is returned by ReadMemoFile if the drive and/or
  223.   directory in the specified filename is invalid. mstReadError is returned by
  224.   ReadMemoFile if an error occurred while reading in the text file.
  225.   mstTooLarge is returned by ReadMemoFile if the file to be read is larger
  226.   than the edit buffer and AllowTruncation is False; if AllowTruncation is
  227.   True, as it is by default, mstTruncated is returned instead.
  228.   mstCreationError is returned by SaveMemoFile if it is unable to create the
  229.   specified file (because the disk is full or is write-protected, for
  230.   example). mstWriteError is returned by SaveMemoFile if an error occurs while
  231.   writing the contents of the edit buffer to disk. mstCloseError indicates
  232.   that an error occurred while attempting to close a file.
  233.  
  234. Procedures and Functions
  235.  
  236. Declaration
  237.   function AddMemoCommand(Cmd : EMtype; NumKeys : Byte;
  238.                           Key1, Key2 : Word) : Boolean;
  239. Purpose
  240.   Add a new command key assignment or change an existing one.
  241. Comments
  242.   This routine can be used to assign a user-defined command to a key
  243.   combination, to disable an existing command, or to change a key assignment.
  244.   See MEMO.PAS for examples of how to use this routine. For a general
  245.   discussion of how to use a function of this type, see pages 14-7 and 14-8 of
  246.   the Turbo Professional manual.
  247.  
  248. Declaration
  249.   procedure DisableMemoMouse;
  250. Purpose
  251.   Disable mouse support in TPMEMO.
  252. Comments
  253.   This routine disables mouse support in TPMEMO. Note that this routine will
  254.   not be included in TPMEMO unless UseMouse is defined.
  255.  
  256. Declaration
  257.   function EditMemo(var EMCB : EMcontrolBlock;
  258.                     ReadOnly : Boolean;
  259.                     var CmdList) : EMtype;
  260. Purpose
  261.   Edit a buffer filled with text.
  262. Comments
  263.   The main routine in TPMEMO, EditMemo is the procedure which processes all
  264.   editing and cursor movement commands. On exit it returns a code indicating
  265.   which command was used to exit the editor (usually EMquit, but possibly a
  266.   user-defined command).
  267.  
  268.   EMCB is a variable containing all pertinent information about an edit window
  269.   and the text buffer associated with it. It must have been initialized
  270.   previously by a call to InitControlBlock.
  271.  
  272.   ReadOnly is used to select read-only mode, in which only non-destructive
  273.   commands are processed. Although this option allows TPMEMO to be used as a
  274.   file browser, the primary reason for providing it is to complement the
  275.   read-only mode in TPENTRY.
  276.  
  277.   Though untyped, CmdList should generally be a variable of the form
  278.  
  279.     MyCmdList : array[1..n] of EMtype;
  280.  
  281.   This array contains a list of commands to be processed by EditMemo
  282.   immediately upon entry to the editor. For example, if you wanted to simulate
  283.   the pressing of <Ctrl PgDn>, you could pass the following variable as the
  284.   CmdList parameter:
  285.  
  286.     MyCmdList : array[1..2] of EMtype = (EMendOfFile, EMnone);
  287.  
  288.   The EMendOfFile command would tell EditMemo to move the cursor to the end of
  289.   the file. The EMnone command signals the end of the list of commands and
  290.   tells EditMemo to resume processing commands entered at the keyboard.
  291.  
  292.   In some cases you may find it necessary to pass text as well as commands. To
  293.   do so, you would simply pass a data structure containing the characters to
  294.   be entered, surrounded by the value EMchar. For example:
  295.  
  296.     MyCmdList : array[1..n] of Char =
  297.       (Char(EMchar), 'h', 'e', 'l', 'l', 'o', Char(EMchar), Char(EMnone);
  298.  
  299.   If you passed this typed constant as the CmdList parameter, the word 'hello'
  300.   would be inserted into the text buffer. The first EMchar signals the start
  301.   of a series of characters to be entered into the text buffer. The second
  302.   EMchar signals the end of the series. And the final EMnone signals the last
  303.   command in the list. (Note that, if you are using Turbo Pascal 4.0, you
  304.   would need to change 'Char(EMchar)' to '#1' and 'Char(EMnone)' to #0 in the
  305.   example above.) When using this facility, please do not try to pass control
  306.   characters as part of a sequence of text.
  307.  
  308.   Two final notes about this routine. First, EditMemo does not 'home the
  309.   cursor' on entry. If an exit command is given and you call EditMemo again
  310.   without calling InitControlBlock first, the cursor will remain where it was
  311.   before the exit command was given. Although this behavior may be undesirable
  312.   in some cases, it is necessary to allow certain kinds of user-defined
  313.   commands to be implemented. Second, EditMemo does not preserve and restore
  314.   the contents of the screen beneath the edit window. It is up to you to do so
  315.   if necessary.
  316. Example
  317.   var
  318.     MyEMCB : EMCB;
  319.   const
  320.     MyCmdList : EMtype = EMnone;
  321.   begin
  322.     InitControlBlock(MyEMCB, ...);
  323.     ...
  324.     ExitCommand := EditMemo(MyEMCB, MyCmdList);
  325.   end;
  326.  
  327.   Edit the text buffer associated with MyEMCB. No special edit commands are to
  328.   be executed on entry to the editor. See MEMO.PAS and ENTRY.PAS for better
  329.   examples of how to use EditMemo.
  330. See Also
  331.   InitControlBlock (TPMEMO)
  332.  
  333. Declaration
  334.   procedure EnableMemoMouse;
  335. Purpose
  336.   Enable mouse support in TPMEMO.
  337. Comments
  338.   This routine enables mouse support in TPMEMO. Note that this routine will
  339.   not be included in TPMEMO unless UseMouse is defined.
  340.  
  341. Declaration
  342.   procedure InitControlBlock(var EMCB : EMcontrolBlock;
  343.                              XLow, YLow, XHigh, YHigh : Byte;
  344.                              TextAttr, CtrlAttr : Byte;
  345.                              InsertOn, IndentOn, WordWrapOn : Boolean;
  346.                              TabSize : Byte; HelpIndex : Word;
  347.                              RightMargin : Byte; LineLimit : Integer;
  348.                              BufferSize : Word; var Buffer);
  349. Purpose
  350.   Initialize a memo editor control block.
  351. Comments
  352.   This routine initializes an 'editor control block', a variable which
  353.   contains all pertinent information about an edit window.
  354.  
  355.   EMCB is the control block to be initialized. XLow, YLow, XHigh, and YHigh
  356.   give the coordinates for the edit window. TextAttr is the video attribute in
  357.   which normal text is to be displayed. CtrlAttr is the video attribute used
  358.   to display control characters; if it is the same as TextAttr, the command
  359.   that allows control characters to be entered (EMctrlChar, normally assigned
  360.   to <Ctrl P>) is disabled. InsertOn indicates whether or not insert mode
  361.   should be On by default. IndentOn indicates whether or not auto-indent mode
  362.   should be On by default. WordWrapOn indicates whether word wrap should be
  363.   enabled by default. TabSize specifies the distance between tab stops.
  364.   HelpIndex is the value that should be passed to a help routine when <F1> is
  365.   pressed. RightMargin indicates the column at which word wrap should occur.
  366.   LineLimit indicates the maximum number of lines that the user may enter.
  367.   Buffer is the edit buffer to be associated with EMCB, and BufferSize
  368.   indicates its size.
  369.  
  370.   InitControlBlock does three things. First, it intializes EMCB with the
  371.   values specified by XLow and the other parameters. Second, it scans the
  372.   contents of the edit buffer to determine how many bytes are in it and how
  373.   many lines of text it contains. (The end of a line is signalled by a
  374.   carriage return-line feed combination; the end of the edit buffer by a ^Z.)
  375.   Third, it resets a few 'housekeeping' variables that are used internally to
  376.   keep track of the cursor, the current line, etc.
  377.  
  378.   See MEMO.PAS and ENTRY.PAS for examples.
  379.  
  380. Declaration
  381.   procedure MemoError(var EMCB : EMcontrolBlock; ErrorCode : Word);
  382. Purpose
  383.   Display error message and wait for key press.
  384. Comments
  385.   This routine provides a 'default' error handler for TPMEMO. You can use it
  386.   as is, or use it as a model for writing your own error handler. MemoError
  387.   displays error messages on the row indicated by ErrorRow in the video
  388.   attribute indicated by ErrorAttr.
  389. Example
  390.   ErrorRow := 1;
  391.   ErrorAttr := $F;
  392.   MemoErrorPtr := @MemoError;
  393.  
  394.   Enables MemoError and requests that error messages be displayed on row 1 in
  395.   white on black.
  396.  
  397. Declaration
  398.   procedure MemoStatus(var EMCB : EMcontrolBlock);
  399. Purpose
  400.   Display a status line.
  401. Comments
  402.   This routine provides a 'default' status display routine for TPMEMO. You can
  403.   use it as is, or use it as a model for writing your own status display
  404.   routine. MemoStatus displays its status line on the row indicated by
  405.   StatusRow in the video attribute indicated by StatusAttr.
  406. Example
  407.   StatusRow := 2;
  408.   StatusAttr := $F;
  409.   MemoStatusPtr := @MemoStatus;
  410.  
  411.   Enables MemoStatus and requests that the status line be displayed on row 2
  412.   in white on black.
  413.  
  414. Declaration
  415.   function ReadMemoFile(var Buffer; BufferSize : Word;
  416.                         FName : string; var FSize : LongInt) : MemoStatusType;
  417. Purpose
  418.   Read a file into Buffer, returning a status code.
  419. Comments
  420.   This routine reads a text file, FName, into a Buffer of BufferSize bytes.
  421.   Upon return, FSize will have the size of FName, if it was found, and the
  422.   function result will indicate whether or not the operation was successful.
  423. Example
  424.   MemoStatus :=
  425.     ReadMemoFile(MyEditBuffer^, MyBufferSize, 'C:\AUTOEXEC.BAT', FSize);
  426.  
  427.   Read C:\AUTOEXEC.BAT into the buffer pointed to by MyEditBuffer.
  428.   MyBufferSize has the size of the edit buffer. On return, FSize has the size
  429.   of the file being edited, if found.
  430.  
  431. Declaration
  432.   function SaveMemoFile(var EMCB : EMcontrolBlock; FName : string;
  433.                         MakeBackup : Boolean) : MemoStatusType;
  434. Purpose
  435.   Save the current file in the text buffer associated with EMCB.
  436. Comments
  437.   This routine saves the contents of the edit buffer associated with EMCB in
  438.   the text file designated by FName. If FName already exists and MakeBackup is
  439.   True, the existing FName will be renamed to FName.BAK before the new file is
  440.   created. Upon return, the function result will indicate whether or not the
  441.   operation was successful.
  442. Example
  443.   MemoStatus := SaveMemoFile(MyEMCB, MyFileName, True);
  444.  
  445.   Save the contents of the edit buffer associated with MyEMCB in MyFileName,
  446.   and make a backup file if appropriate.
  447.  
  448. The following routines are intended primarily for internal use, but they have
  449. been interfaced in case you need them in order to implement user-defined
  450. commands or for other purposes. These routines are not fully documented, so if
  451. you want to use one of them you will need to study the source code for TPMEMO.
  452.  
  453.   function FindLineIndex(var EMCB : EMcontrolBlock; LineNum : Integer) : Word;
  454.     {-Return the index into the edit buffer for the specified line number.
  455.       LineNum must be <= EMCB.TotalLines.}
  456.  
  457.   function FindLineLength(var EMCB : EMcontrolBlock; LineNum : Integer) : Word;
  458.     {-Find the length of the specified line}
  459.  
  460.   procedure InitBufferState(var EMCB : EMcontrolBlock;
  461.                             BufferSize : Word; var Buffer);
  462.     {-Initialize the edit buffer status fields in a control block}
  463.  
  464.   procedure GetLine(var EMCB : EMcontrolBlock;
  465.                     var S : string; LineNum : Integer);
  466.     {-Get the LineNum'th line from the buffer for the specified control block
  467.       and store it in S. If line is longer than 255 characters, only the first
  468.       255 characters will be loaded into S.}
  469.  
  470.   procedure DrawLine(var EMCB : EMcontrolBlock;
  471.                      St : String; LineNum : Integer);
  472.     {-Draw the string St, which represents the specified line number}
  473.  
  474.   procedure FastWriteCtrl(St : String; Row, Col, Attr, Ctrl : Byte);
  475.     {-Write St at Row,Col in Attr (video attribute) without snow.
  476.       Control characters displayed in Ctrl as upper-case letters}
  477.  
  478. Editing Commands
  479. ------------------------------------------------------------------------------
  480.  
  481. TPMEMO offers a fairly complete set of basic editing commands. The available
  482. commands are listed below. In each case the first line gives the name of the
  483. command, in TPMEMO's terms, followed by the key(s) to which it is normally
  484. assigned. The second and following lines give a brief description of the
  485. command.
  486.  
  487.    EMleft        <Left>, <CtrlS>
  488.    Cursor left one character.
  489.  
  490.    EMright       <Right>, <CtrlD>
  491.    Cursor right one character.
  492.  
  493.    EMwordLeft    <CtrlLeft>, <CtrlA>
  494.    Cursor left one word. If the cursor is at the beginning of a line, it is
  495.    moved to the end of the previous line.
  496.  
  497.    EMwordRight   <CtrlRight>, <CtrlF>
  498.    Cursor right one word. If the cursor is at the end of a line, it is moved
  499.    to the beginning of the following line.
  500.  
  501.    EMhome        <Home>, <CtrlQ><S>
  502.    Cursor to beginning of line.
  503.  
  504.    EMend         <End>, <CtrlQ><D>
  505.    Cursor to end of line.
  506.  
  507.    EMup          <Up>, <CtrlE>
  508.    Cursor up one line.
  509.  
  510.    EMdown        <Down>, <CtrlX>
  511.    Cursor down one line.
  512.  
  513.    EMscrollUp    <CtrlW>
  514.    Scroll display up one line.
  515.  
  516.    EMscrollDown  <CtrlZ>
  517.    Scroll display down one line.
  518.  
  519.    EMpageUp      <PgUp>, <CtrlR>
  520.    Scroll display up one page.
  521.  
  522.    EMpageDown    <PgDn>, <CtrlC>
  523.    Scroll display down one page.
  524.  
  525.    EMscreenTop   <CtrlHome>, <CtrlQ><E>
  526.    Move cursor to top of edit window.
  527.  
  528.    EMscreenBot   <CtrlEnd>, <CtrlQ><X>
  529.    Move cursor to bottom of edit window.
  530.  
  531.    EMtopOfFile   <CtrlPgUp>, <CtrlQ><R>
  532.    Move cursor to beginning of file.
  533.  
  534.    EMendOfFile   <CtrlPgDn>, <CtrlQ><C>
  535.    Move cursor to end of file.
  536.  
  537.    EMdel         <Del>, <CtrlG>
  538.    Delete character at cursor.
  539.  
  540.    EMback        <Bksp>, <CtrlH>, <CtrlBksp>
  541.    Delete character to left of cursor. If the cursor is at the beginning of a
  542.    line, the line will be joined with the previous line.
  543.  
  544.    EMdelLine     <CtrlY>
  545.    Delete current line.
  546.  
  547.    EMdelEol      <CtrlQ><Y>
  548.    Delete from cursor to end of line.
  549.  
  550.    EMdelWord     <CtrlT>
  551.    Delete word to right of cursor. If the cursor is at end of a line, the
  552.    following line is joined with the current line.
  553.  
  554.    EMenter       <Enter>, <CtrlM>
  555.    Start a new line.
  556.  
  557.    EMtab         <Tab>, <CtrlI>
  558.    Move the cursor to the next tab stop. If insert mode is on, any text to the
  559.    right of the cursor is moved to the right of the tab stop.
  560.  
  561.    EMctrlChar    <CtrlP>
  562.    Insert control character. For example, to insert a ^G, you would enter
  563.    <CtrlP><CtrlG>. This command is available only if the video attribute for
  564.    control characters is different than that for normal characters. Control
  565.    characters are displayed as uppercase alphabetics (^G is displayed as 'G',
  566.    for example) in the specified attribute.
  567.  
  568.    EMins         <Ins>, <CtrlV>
  569.    Toggle insert mode on and off. A fat cursor indicates insert mode; a thin
  570.    cursor indicates overtype mode.
  571.  
  572.    EMindent      <CtrlO><I>
  573.    Toggle auto-indent mode on or off. In auto-indent mode, pressing <Enter>
  574.    while in insert mode will cause the new line inserted to have the same
  575.    indentation level as the previous line. Auto-indent mode also affects the
  576.    way that text is formatted when word wrap occurs--the new line will have
  577.    the same indentation level as the previous line--and hence the behavior of
  578.    the reformatting commands (<CtrlB> and <AltR>).
  579.  
  580.    EMwordWrap    <CtrlO><W>
  581.    Toggle word wrap on and off. When word wrap is on, any attempt to insert or
  582.    append text beyond the right margin will cause a new line to be inserted
  583.    following the current line and all words that are at least partially
  584.    beyond the right margin to be moved to the new line.
  585.  
  586.    EMreformatP   <CtrlB>
  587.    Reformat the current paragraph.
  588.  
  589.    EMreformatG   <AltR>
  590.    Reformat the entire file. Use this command with caution.
  591.  
  592.    EMrestore     <CtrlQ><L>
  593.    Restore original contents of the current line.
  594.  
  595.    EMhelp        <F1>, <ClickBoth>
  596.    Help. If a user-written help routine has been established by setting
  597.    MemoHelpPtr to a value other than nil, pressing <F1> will call that
  598.    routine; otherwise this command does nothing.
  599.  
  600.    EMquit        <Esc>, <CtrlBreak>, <ClickRight>
  601.    Quit editing.
  602.  
  603.    EMmouse       <ClickLeft>
  604.    Move the cursor to the position indicated by the mouse.
  605.  
  606. In addition to the commands described above, TPMEMO has made provisions for up
  607. to 20 user-defined commands (EMuser0..EMuser19). See the section on
  608. Programming Hooks, below, for details.
  609.  
  610. Programming Hooks
  611. ------------------------------------------------------------------------------
  612.  
  613. TPMEMO implements many of the same kinds of hooks as TPEDIT, TPENTRY, and
  614. several of the other Turbo Professional 5.0 units do. (See Appendix C of the
  615. Turbo Professional manual.) These hooks are:
  616.  
  617.   MemoKeyPtr
  618.   ----------
  619.   This variable points to the routine used to obtain keyboard input. See pages
  620.   14-11 and 14-12 of the Turbo Professional manual for details on how to use a
  621.   pointer variable of this type.
  622.  
  623.   MemoHelpPtr
  624.   -----------
  625.   This variable points to the routine to be called when a request for help is
  626.   issued by the user. See pages 14-13 through 14-15 of the Turbo Professional
  627.   manual for details on how to use a pointer variable of this type. TPMEMO
  628.   passes three parameters to the help routine:
  629.  
  630.     UnitCode   : HelpForMemo (a constant in TPMEMO)
  631.     IDptr      : the address of the current editor control block
  632.     HelpIndex  : the help index associated with the current control block
  633.  
  634.   It is imperative that a help routine be declared FAR and that it not be
  635.   nested inside another procedure.
  636.  
  637.   MemoKeyMax, MemoKeyID, and MemoKeySet
  638.   -------------------------------------
  639.   These constants together provide an 'installable keyboard hook', as defined
  640.   on pages 14-6 through 14-10 of the Turbo Professional manual. The
  641.   AddMemoCommand routine mentioned above is analogous to the AddEditCommand
  642.   routine documented on page 14-7 and 14-8. As indicated earlier, TPMEMO sets
  643.   aside space for up to 20 user-defined commands (EMuser0..EMuser19).
  644.  
  645. TPMEMO also provides a couple of hooks for which there is no real counterpart
  646. in any of the standard Turbo Professional units. These hooks are:
  647.  
  648.   MemoErrorPtr
  649.   ------------
  650.   This variable points to a routine that will display error messages when an
  651.   error occurs. It must be of the form:
  652.  
  653.     {$F+}
  654.     procedure ErrorRoutine(var EMCB : EMcontrolBlock; ErrorCode : Word);
  655.     begin
  656.     end;
  657.     {$F-}
  658.  
  659.   The EMCB parameter is the current editor control block. ErrorCode indicates
  660.   the type of error that occurred. The four possible values are:
  661.  
  662.     tmBufferFull    = 1;       {edit buffer is full}
  663.     tmLineTooLong   = 2;       {line too long, CRLF inserted}
  664.     tmTooManyLines  = 3;       {max line limit exceeded}
  665.     tmOverLineLimit = 4;       {max line limit already exceeded}
  666.  
  667.   For an example of an error routine, see the MemoError procedure in
  668.   TPMEMO.PAS. It is imperative that an error routine be declared FAR and that
  669.   it not be nested inside another procedure.
  670.  
  671.   MemoStatusPtr
  672.   -------------
  673.   This variable points to a routine that will display status information while
  674.   editing is taking place. It must be of the form:
  675.  
  676.     {$F+}
  677.     procedure StatusRoutine(var EMCB : EMcontrolBlock);
  678.     begin
  679.     end;
  680.     {$F-}
  681.  
  682.   The one parameter passed to a status routine is the current editor control
  683.   block. For an example of a status routine, see the MemoStatus procedure in
  684.   TPMEMO.PAS. It is imperative that a status routine be declared FAR and that
  685.   it not be nested inside another procedure.
  686.  
  687.   UserData field in an EMcontrolBlock
  688.   -----------------------------------
  689.   The first field in a variable of type EMcontrolBlock is a pointer called
  690.   'UserData'. This space is set aside for you to use as you see fit. You could
  691.   use it to store a pointer to a filename or a related data structure, or you
  692.   might typecast the pointer to a longint and use it to store an ID number
  693.   (this might be useful if you have multiple editing windows open or multiple
  694.   memo fields in a database record):
  695.  
  696.      var
  697.        EMCB : EMcontrolBlock;
  698.      begin
  699.        LongInt(EMCB.UserData) := 1;
  700.        InitControlBlock(EMCB, ...);
  701.      end;
  702.  
  703.   No routine in TPMEMO ever uses this field. It is provided strictly for your
  704.   convenience in cases where you need it.
  705.  
  706. Compiling TPMEMO
  707. ------------------------------------------------------------------------------
  708.  
  709. Like many of the units in Turbo Professional 5.0, TPMEMO contains several
  710. conditional compilation directives that affect the size and capabilities of
  711. the unit. At present, TPMEMO depends on only a single conditional define in
  712. TPDEFINE.INC, 'UseMouse'. If UseMouse is defined, TPMEMO can use the mouse
  713. handling routines in TPMOUSE to provide built-in mouse support. (Note that you
  714. must call EnableMemoMouse in order to actually enable mouse support.) If you
  715. don't need mouse support, you should undefine UseMouse in TPDEFINE.INC
  716. before compiling TPMEMO.
  717.  
  718. Example Programs
  719. ------------------------------------------------------------------------------
  720.  
  721. TPMEMO.ARC contains two programs to demonstrate the use of TPMEMO, ENTRY.PAS
  722. and MEMO.PAS. Together, these two programs provide an ample demonstration of
  723. what can be done with TPMEMO.
  724.  
  725. The copy of ENTRY.PAS provided here is a slightly modified version of the demo
  726. program that comes with Turbo Professional 5.00 and 5.01. The main difference
  727. between them is that the Notes field can contain up to 2K of notes, not just
  728. 255 characters. To see TPMEMO in action, move the cursor to the Notes field
  729. and press <Enter>. You should also be sure to rebuild the help file for the
  730. program using the copy of ENTRY.TXT provided here. To do so, enter
  731.  
  732.    MAKEHELP entry.txt /q
  733.  
  734. at the DOS prompt. You will then be able to get help about the memo editor
  735. from within ENTRY.
  736.  
  737. MEMO.PAS is a simple text editor based on TPMEMO. To use it, enter
  738.  
  739.    MEMO filename
  740.  
  741. where filename is the name of the file to be entered. In addition to the
  742. editing commands described above, MEMO implements three user-defined commands:
  743.  
  744.    EMuser0       <CtrlK><S>, <F2>
  745.    Save file and continue editing.
  746.  
  747.    EMuser1       <CtrlK><X>, <Ctrl F2>
  748.    Save file and exit.
  749.  
  750.    EMuser2       <CtrlK><Q>, <Alt F2>
  751.    Abandon file. If the file has been modified, you will be asked to confirm
  752.    that you want to quit without saving the changes. As implemented, this
  753.    command is equivalent to the EMquit command.
  754.  
  755. If you are at all familiar with the Turbo Pascal editor, you should find the
  756. behavior of MEMO quite intuitive. Keep in mind, however, that TPMEMO does not
  757. implement any of the block-related commands found in TURBO's editor.
  758.  
  759. Miscellaneous Notes
  760. ------------------------------------------------------------------------------
  761.  
  762.   The Modified Flag
  763.   -----------------
  764.   The Modified flag in an editor control block indicates whether or not any
  765.   changes have been made to the edit buffer. This flag is temporarily set any
  766.   time that a change is made to the text of a line. If the changes made are
  767.   undone (either manually or using the restore line command, <CtrlQ><L>), the
  768.   flag will be reset to its previous state. Once the cursor is moved from a
  769.   modified line, the flag will remain set until it is cleared by a call to
  770.   InitControlBlock or SaveMemoFile.
  771.  
  772.   Reentrancy
  773.   ----------
  774.   The editor in TPMEMO is completely reentrant. That is, it does not alter any
  775.   global variables other than the editor control block passed to it (which may
  776.   or may not be a global variable). The main implication of this feature is
  777.   that it is possible for a user-written routine called by EditMemo to in turn
  778.   call EditMemo to edit a second file or memo field. Although the Turbo
  779.   Professional manual does not mention it, the screen manager in TPENTRY is
  780.   also reentrant in the same sense.
  781.  
  782.   Edit Window Size, Etc.
  783.   ----------------------
  784.   The minimum size of an edit window is 1 row x 1 column, although you would
  785.   obviously never want a window that narrow. You might, in unusual cases, want
  786.   a one-row window, however, because it is technically possible to use TPMEMO
  787.   as a line editor (like TPEDIT). To do so, you would
  788.  
  789.     - specify a one-row window (YLow = YHigh) in the call to InitControlBlock
  790.     - specify a LineLimit parameter of 1 in the call to InitControlBlock
  791.     - and, optionally, set MaxLineLength to the width of the edit window less
  792.       1 (be sure to reset MaxLineLength to 127 afterward)
  793.  
  794.   This might be useful in cases where TPMEMO is needed in a program, and you
  795.   want to avoid pulling in TPEDIT. Keep in mind, however, that <Enter> is not
  796.   an exit command in TPMEMO. You would probably want to temporarily reassign
  797.   <Enter> to an exit command such as EMuser0 if you are going to do this.
  798.  
  799.   Tabs
  800.   ----
  801.   TPMEMO inserts 'tabs' by adding the appropriate number of spaces to a line.
  802.   It is not equipped to handle 'hard tabs' (ASCII 9).
  803.  
  804.   Line Limit in Editor
  805.   --------------------
  806.   Although the memo field editor allows you to specify a limit on the number
  807.   of lines that the user may enter, that limit is not enforced in two cases:
  808.   when the buffer contains too many lines before editing begins, and when text
  809.   is being reformatted (there's no good way to determine in advance how many
  810.   lines there will be after reformatting). In both cases, the editor will
  811.   simply generate the 'tmOverLineLimit' error.
  812.